use std::collections::BTreeMap;
use std::fmt;
use std::fmt::Formatter;
use serde::{de, Deserialize, Deserializer};
use serde::de::Visitor;

#[derive(Debug, Default)]
pub struct Exec {
    pub cmd : String ,
    pub args : Vec<String> ,  // 普通参数
    pub named : BTreeMap<String,String> , // 命名参数
}


// 通过&str转成cmd封装起来
impl From<&str> for Exec {
    fn from(value: &str) -> Self {
        let mut exec = Self::default(); 
        for x in value.split_whitespace(){
            if x.starts_with("--") {
                // 命名参数
                let mut it = x[2..].splitn(2,"=") ;
                let name = it.next().unwrap() ;
                let value = it.next().unwrap_or("" ) ;
                exec.named.insert(name.to_string(),value.to_string()) ; 
            }else if exec.cmd.is_empty() {
                exec.cmd = x.to_string();
            } else {
                exec.args.push(x.to_string());
            }
        }
        exec 
    }
}


impl Exec{
    // deserialize可以灵活从多种格式数据反序列化出Exec实例的列表
    pub fn deserialize<'de,D>(deserializer:D) -> Result<Vec<Exec>,D::Error> 
    where D:Deserializer<'de> , {
        struct ExecVisitor ;   // 内部结构体
        impl <'de> Visitor<'de> for ExecVisitor {
            type Value = Vec<Exec> ;
            // 反序列化失败提供的信息
            fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
                formatter.write_str("a command string, e.g. tab_switch 0")
            }
            
            // 处理序列类型的输入
            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
            where
                A: de::SeqAccess<'de>,
            {
                let mut execs = Vec::new();
                while let Some(value) = &seq.next_element::<String>()? {
                    execs.push(Exec::from(value.as_str()));
                }
                Ok(execs)
            }

            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
            where
                E: de::Error,
            {
                Ok(value.split(';').map(Exec::from).collect())
            }
        }
        
        deserializer.deserialize_any(ExecVisitor)
    }
}

// 下面是解析命令的另一种实现方式  可以应对 --all = True 这种空格分离的问题
// 
// impl From<&str> for Exec {
//     fn from(value: &str) -> Self {
//         let mut exec = Self::default();
//         let mut parts: Vec<String> = value.split_whitespace().map(|s| s.to_string()).collect();
// 
//         // 合并相邻的部分
//         let mut i = 0;
//         while i < parts.len() {
//             if parts[i].starts_with("--") && i + 1 < parts.len() {
//                 parts[i] = format!("{}={}", parts[i], parts.remove(i + 1));
//             } else {
//                 i += 1;
//             }
//         }
// 
//         for x in parts {
//             if x.starts_with("--") {
//                 let mut it = x[2..].splitn(2, '=');
//                 let name = it.next().unwrap();
//                 let value = it.next().unwrap_or("");
//                 exec.named.insert(name.to_string(), value.to_string());
//             } else if exec.cmd.is_empty() {
//                 exec.cmd = x.to_string();
//             } else {
//                 exec.args.push(x.to_string());
//             }
//         }
// 
//         exec
//     }
// }